

#include "xlibrary_config.h"

#if LIBRARY_KB_ENABLE

#include <string.h>

#include "kb.h"
#include "trace.h"

#define KB_TIME_BASE                 (INTERVAL_OF_KB_TIMER) // unit: ms 

#define KB_CLICK_TIME            (KB_CLICK_MIN_TIME/KB_TIME_BASE)
#define KB_SHORT_TIME            (KB_SHORT_MIN_TIME/KB_TIME_BASE)
#define KB_LONG_TIME             (KB_LONG_MIN_TIME/KB_TIME_BASE)
#define KB_HOLD_TIME             (KB_INTERVAL_OF_HOLD_EVT/KB_TIME_BASE)
//extern uint8_t test_flag ;

void kb_reset(kb_t * p_kb)
{    
    memset( p_kb, 0, sizeof(kb_t) );
}

// require to call kb reset first to re-register event callback 
void kb_callback_register(kb_t * p_kb, kb_evt_handle_t cb){
    if( p_kb->handle == NULL ){
        p_kb->handle = cb;
    }
}

/**@brief keyboard process function
 * @param p_kb : keyboard instance 
 * @param flags_of_pin_press: if pin press, set relate index to 1, else set to 0
 * @return  1 - process done
 *          0 - under going 
 */ 
int kb_process(kb_t * p_kb, uint32_t flags_of_pin_press)
{
    if( p_kb->handle == 0){ // if does not has callback handle, exit this
        return 1; 
    }

    uint32_t flags_release_cnt = 0;
    kb_key_t * p_kb_key;
    kb_evt_t evt; 

    for(int i = 0; i < p_kb->nums; i++)
    {
        p_kb_key = &p_kb->p_key_list[i];

        if( (flags_of_pin_press & ( KB_KEY_STATE_PRESSED << i )) > 0)
        {
            if(p_kb_key->last_state == KB_KEY_STATE_PRESSED)
            {
                p_kb_key->debounce ++;

                if( p_kb_key->debounce == KB_SHORT_TIME)
                {
                    p_kb_key->evt = KB_EVT_SHORT_HOLD_READY;
                    evt.type = KB_EVT_SHORT_HOLD_READY;
                    evt.idx = i; 
                    p_kb->handle( &evt );
                }

                #if KB_SUPPORT_HOLD
                if( p_kb_key->debounce > KB_SHORT_TIME )
                {
                    p_kb_key->hold ++;
                    if( p_kb_key->hold >= KB_HOLD_TIME )
                    {
                        p_kb_key->hold = 0;

                        evt.type = KB_EVT_HOLD;
                        evt.idx = i;
                        p_kb->handle( &evt );
                    }
                }
                #endif 

                if( p_kb_key->debounce == KB_LONG_TIME )
                {
                    p_kb_key->evt = KB_EVT_LONG_HOLD;
                    evt.type = KB_EVT_LONG_HOLD;
                    evt.idx = i; 
                    p_kb->handle( &evt );
                }
                else
                {
                    // do nothings 
                }
            }
            else 
            {//reset debounce count 
                p_kb_key->debounce = 0; 
                p_kb_key->evt = KB_EVT_PRESS; 
                evt.type = KB_EVT_PRESS;
                evt.idx = i; 
                p_kb->handle( &evt );
            }
            p_kb->p_key_list[i].last_state = KB_KEY_STATE_PRESSED; 
        }
        else 
        {
            if( p_kb_key->last_state == KB_KEY_STATE_RELEASE )
            {
                if( p_kb_key->evt != KB_EVT_RELEASE)
                {
                    p_kb_key->evt = KB_EVT_RELEASE;
                    evt.type = KB_EVT_RELEASE;
                    evt.idx = i; 
                    p_kb->handle( &evt );
                }
                flags_release_cnt ++;
            }
            else
            {
                if( p_kb_key->evt != KB_EVT_RELEASE)
                {
                    if( p_kb_key->debounce >= KB_LONG_TIME)
                    {
                        // do nothings 
                    }
                    else if( p_kb_key->debounce > KB_SHORT_TIME)
                    {
                        p_kb_key->evt = KB_EVT_SHORT_HOLD_RELEASE;
                        evt.type = KB_EVT_SHORT_HOLD_RELEASE;
                        evt.idx = i; 
                        p_kb->handle( &evt );
                    }
                    else if( p_kb_key->debounce > KB_CLICK_TIME)
                    {
                        p_kb_key->evt = KB_EVT_CLICK;
                        evt.type = KB_EVT_CLICK;
                        evt.idx = i;
                        p_kb->handle( &evt );
                    }
                    else
                    {

                    }
                }
            }
            p_kb->p_key_list[i].last_state = KB_KEY_STATE_RELEASE; 
        }        
    }
    
    if( flags_release_cnt == p_kb->nums ) 
    {
        evt.idx = KB_ALL_KEY; 
        evt.type = KB_EVT_RELEASE; 
        p_kb->handle( &evt );  //all release 
    }
     // APP_PRINT_INFO3("[key]-2 evt.idx=%d,%d,%d\r\n",evt.idx,test_flag,flags_of_pin_press);
    return (flags_release_cnt == p_kb->nums); //return every key has release state 
}

#endif // !LIBRARY_KB_ENABLE
